package com.ruoyi.util.http;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * @Description: http://www.pianshen.com/article/1757316634/
 * @ClassName: HttpClientUtils
 * @author: wangwk
 * @date: 2019年10月29日 下午12:51:45
 * 	这个没有测试过
 */
public class HttpClientUtil {
	private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class);

	/**
	 * @Description: 功能描述
	 * 		UrlEncodedFormEntity 来设置 body，消息体内容类似于“KEY1=VALUE1&KEY2=VALUE2&...”这种形式
	 * 		UrlEncodeFormEntity继承StringEntity ，可以认为指定类型的entity，说到指定类型，UrlEncodeFormEntity
	 * 		默认指定了他的ContentType就是application/x-www-form-urlencoded，所以使用这个类做参数，
	 * 		会将参数以key1=value1&key2=value2的键值对形式发出。类似于传统的application/x-www-form-urlencoded表单上传。
	 * 
	 * @param: 参数描述
	 * @param url
	 * @param headerMap
	 * @param jsonObject
	 * @param charset
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:34:31
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String HttpPostPair(String url, Map<String, String> headerMap, JSONObject jsonObject, String charset) {
		String result = null;
		try {
			if (StringUtils.isBlank(charset)) {
				charset = "UTF-8";
			}
			List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
			if (jsonObject != null) {
				String value = null;
				for (String key : jsonObject.keySet()) {
					value = jsonObject.getString(key);
					if (StringUtils.isNotBlank(value)) {
						list.add(new BasicNameValuePair(key, value)); 
					}
				}
			}
			result = HttpPost(url, headerMap, new UrlEncodedFormEntity(list, charset), charset);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return result;
	}

	/**
	 * @Description: 功能描述
	 * 		上传文件
	 * 
	 * @param: 参数描述
	 * @param url
	 * @param headerMap
	 * @param fileName
	 * @param file
	 * @param charset
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午4:38:50
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String HttpPostUploadFile(String url, Map<String, String> headerMap, String fileName, File file, String charset) {
		String result = null;
		HttpEntity entity = null;
		try {
			if (StringUtils.isBlank(charset)) {
				charset = "UTF-8";
			}
			FileBody fileBody = new FileBody(file);
            StringBody comment = new StringBody(fileName, ContentType.TEXT_PLAIN);
            entity = MultipartEntityBuilder.create().addPart("file", fileBody).addPart("fileName", comment).build();
			result = HttpPost(url, headerMap, entity, charset);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (entity != null) {
		            EntityUtils.consume(entity);
				}
			} catch (Exception e) {
				log.error(e.toString());
				log.error(e.toString());
			}
		}
		return result;
	}
	
	/**
	 * @Description: 功能描述
	 * 		采用 StringEntity 就是形式比较自由了，除了json，你也可以使用其它任意的字符串，只要服务端能做相应处理即可。
	 * 		StringEntity可以用来灵活设定参数格式形式，而UrlEncodeFormEntity则适合于传统表单格式的参数形式，至于到底用什么形式，也要看请求目标服务的数据接收形式
	 * 
	 * @param: 参数描述
	 * @param url
	 * @param headerMap
	 * @param jsonObject
	 * @param charset
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:33:48
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String HttpPostJSONObject(String url, Map<String, String> headerMap, JSONObject jsonObject, String charset) {
		if (StringUtils.isBlank(charset)) {
			charset = "UTF-8";
		}
		if (jsonObject == null) {
			jsonObject = new JSONObject();
		}
		return HttpPost(url, headerMap, new StringEntity(jsonObject.toString(), charset), charset);
	}
	
	/**
	 * @Description: 功能描述
	 * 		采用 StringEntity 就是形式比较自由了，除了json，你也可以使用其它任意的字符串，只要服务端能做相应处理即可。
	 * 
	 * @param: 参数描述
	 * @param url
	 * @param headerMap
	 * @param jsonArray
	 * @param charset
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:35:29
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String HttpPostJSONArray(String url, Map<String, String> headerMap, JSONArray jsonArray, String charset) {
		if (StringUtils.isBlank(charset)) {
			charset = "UTF-8";
		}
		if (jsonArray == null) {
			jsonArray = new JSONArray();
		}
		return HttpPost(url, headerMap, new StringEntity(jsonArray.toString(), charset), charset);
	}
	
	/**
	 * @Description: 功能描述
	 * 		POST请求
	 * 
	 * @param: 参数描述
	 * @param url			地址
	 * @param headerMap		头文件信息
	 * @param entity		发送内容
	 * @param charset		内容类型
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:35:56
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String HttpPost(String url, Map<String, String> headerMap, HttpEntity entity, String charset) {
		HttpPost httpPost = null;
		String result = null;
		try {
			/**
			 * 	创建HttpClient实例
			 */
			CloseableHttpClient httpClient = HttpClientBuilder.create().build();
			httpPost = new HttpPost(url);
			if (StringUtils.isBlank(charset)) {
				charset = "UTF-8";
			}
			/**
			 * 	设置头信息
			 */
			if (headerMap != null) {
				for (String name : headerMap.keySet()) {
					httpPost.addHeader(name, headerMap.get(name));
				}
			}
			/**
			 *	设置内容
			 */
			if (entity != null) {
				httpPost.setEntity(entity);
			}
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					result = EntityUtils.toString(resEntity, charset);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (httpPost != null) {
					httpPost.abort();
				}
			} catch (Exception e) {
				log.error(e.toString());
			}
		}
		return result;
	}
	
	/**
	 * @Description: 功能描述
	 * 		向指定URL发送GET方法的请求
	 * 
	 * @param: 参数描述
	 * @param url      发送请求的URL
	 * @param paramMap 请求参数集合信息，存储格式为key-value对应方式。
	 * @param charset  请求参数的内容编码格式。
	 * @return	所代表远程资源的响应结果
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:38:39
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static InputStream sendGetInputStream(String url, Map<String, String> headerMap, Map<String, String> paramMap, String charset) {
		try {
			if (StringUtils.isBlank(url)) {
				return null;
			}
			if (StringUtils.isBlank(charset)) {
				charset = "UTF-8";
			}
			StringBuilder stringBuilder = new StringBuilder();
			if (paramMap != null) {
				for (String key : paramMap.keySet()) {
					String value = paramMap.get(key);
					if (StringUtils.isNotBlank(value)) {
						if (stringBuilder.length() > 0) {
							stringBuilder.append("&");
						}
						stringBuilder.append(key).append("=").append(URLEncoder.encode(value, charset));
					}
				}
			}
			URL realUrl = null;
			if (stringBuilder != null && stringBuilder.length() > 0) {
				realUrl = new URL(url + "?" + stringBuilder.toString());
			} else {
				realUrl = new URL(url);
			}
			/**
			 * 	打开和URL之间的连接
			 */
			URLConnection connection = realUrl.openConnection();
			/**
			 * 	设置通用的请求属性
			 */
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			/**
			 * 	设置头信息
			 */
			if (headerMap != null) {
				for (String name : headerMap.keySet()) {
					connection.setRequestProperty(name, headerMap.get(name));
				}
			}
			connection.setConnectTimeout(1000 * 30);
			/**
			 * 	不使用缓存
			 */
			connection.setUseCaches(false);
			/**
			 * 	建立实际的连接
			 */
			connection.connect();
			return connection.getInputStream();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 功能描述
	 * 		向指定URL发送GET方法的请求
	 * 
	 * @param: 参数描述
	 * @param url      	发送请求的URL
	 * @param paramMap 	请求参数集合信息，存储格式为key-value对应方式。
	 * @param charset  	请求参数的内容编码格式。
	 * @return
	 * @throws: 异常描述
	 *
	 * @version: v1.0.3
	 * @author: wangwk
	 * @date: 2021年9月13日 下午3:32:01
	 *
	 * Modification History:
	 * Date         Author          Version            Description
	 * ---------------------------------------------------------*
	 * 2021年9月13日   wangwk          v1.0.3.1               创建
	 */
	public static String sendGet(String url, Map<String, String> headerMap, Map<String, String> paramMap, String charset) {
		String result = null;
		InputStream inputStream = null;
		BufferedReader bufferedReader = null;
		try {
			if (StringUtils.isBlank(charset)) {
				charset = "UTF-8";
			}
			inputStream = sendGetInputStream(url, headerMap, paramMap, charset);
			if (inputStream != null) {
				/**
				 * 	 定义BufferedReader输入流来读取URL的响应
				 */
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream, charset));
				String line;
				while ((line = bufferedReader.readLine()) != null) {
					if (result == null) {
						result = line;
					} else {
						result += line;
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (bufferedReader != null) {
					bufferedReader.close();
				}
			} catch (Exception ex) {
				log.error(ex.toString());
			}
			try {
				if (inputStream != null) {
					inputStream.close();
				}
			} catch (Exception ex) {
				log.error(ex.toString());
			}
		}
		return result;
	}
	
}
